/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package wf3.servlet;

import acceso.util.Escritor;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.RGBImageFilter;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import wf3.gps.ClusterIconChange;

/**
 *
 * @author john
 */
public class ImageUtil extends HttpServlet {
    
    public static final int ALPHA = 0;
    public static final int RED = 1;
    public static final int GREEN = 2;
    public static final int BLUE = 3;
    
    public static final int HUE = 0;
    public static final int SATURATION = 1;
    public static final int BRIGHTNESS = 2;
    
    public static final int TRANSPARENT = 0;

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
//        response.setContentType("text/html;charset=UTF-8");
        response.setContentType("image/jpeg");
        OutputStream out = response.getOutputStream();
        try {
            String xact = request.getParameter("xact");
            switch (xact) {
                case "2": {
                    int nu_angulo = Integer.parseInt(request.getParameter("nu_angulo"));//angulo del vehiculo
                    String no_colore = request.getParameter("no_color") == null ? "ffffff" : request.getParameter("no_color");//color
                    Color co_color = new Color(Integer.valueOf(no_colore.substring(0, 2), 16), Integer.valueOf(no_colore.substring(2, 4), 16), Integer.valueOf(no_colore.substring(4, 6), 16));
                    BufferedImage cr = colorImage(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/ico_circu.png")), co_color, Color.WHITE);
                    BufferedImage ta = aplicarFiltro(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/ico_taxi.png")), Color.RED, co_color);
                    BufferedImage cir = new BufferedImage(cr.getWidth(), cr.getHeight(), cr.getType());
                    AffineTransform tx = new AffineTransform();
                    tx.rotate(Math.toRadians(nu_angulo), cr.getWidth() / 2, cr.getHeight() / 2);
                    
                    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
                    cir = op.filter(cr, null).getSubimage(0, 0, 50, 50);
                    
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    ((Graphics2D) cir.getGraphics()).drawImage(ta, ((cr.getWidth() - ta.getWidth()) / 2), ((cr.getHeight() - ta.getHeight()) / 2), null);
                    ImageIO.write(cir, "png", out);
                    break;
                }
                case "3": {
                    int nu_angulo = Integer.parseInt(request.getParameter("nu_angulo"));
                    BufferedImage oldImage = ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/moto.png"));
                    BufferedImage newImage = new BufferedImage(oldImage.getHeight(), oldImage.getWidth(), oldImage.getType());
                    Graphics2D graphics = (Graphics2D) newImage.getGraphics();
                    graphics.rotate(Math.toRadians(nu_angulo), newImage.getWidth() / 2, newImage.getHeight() / 2);
                    graphics.translate((newImage.getWidth() - oldImage.getWidth()) / 2, (newImage.getHeight() - oldImage.getHeight()) / 2);
                    graphics.drawImage(oldImage, 0, 0, oldImage.getWidth(), oldImage.getHeight(), null);
                    ImageIO.write(newImage, "png", out);
                    break;
                }
                case "4": {
//                    int nu_angulo = Integer.parseInt(request.getParameter("nu_angulo"));//angulo del vehiculo
//                    String no_colore = request.getParameter("no_color") == null ? "ffffff" : request.getParameter("no_color");//color
//                    Color co_color = new Color(Integer.valueOf(no_colore.substring(0, 2), 16), Integer.valueOf(no_colore.substring(2, 4), 16), Integer.valueOf(no_colore.substring(4, 6), 16));
//
//                    BufferedImage arrow = colorImage(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/arrow.png")), co_color, null);
//                    BufferedImage arrowR = new BufferedImage(arrow.getHeight(), arrow.getWidth(), arrow.getType());
//                    AffineTransform tx = new AffineTransform();
//                    tx.rotate(Math.toRadians(nu_angulo), arrow.getWidth() / 2, arrow.getHeight() / 2);
//
//                    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
//                    arrowR = op.filter(arrow, null).getSubimage(0, 0, 24, 24);
//
//                    ImageIO.write(arrowR, "png", out);
//                    Escritor.escribe_debug("-->img:" + getServletContext().getRealPath("/"));
                    int nu_angulo = Integer.parseInt(request.getParameter("nu_angulo"));//angulo del vehiculo
                    String no_colore = request.getParameter("no_color") == null ? "ffffff" : request.getParameter("no_color");//color
                    Color co_color = new Color(Integer.valueOf(no_colore.substring(0, 2), 16), Integer.valueOf(no_colore.substring(2, 4), 16), Integer.valueOf(no_colore.substring(4, 6), 16));
                    BufferedImage cr = colorImage(ImageIO.read(new File(getServletContext().getRealPath("/") + "/img/geo/ico_circu.png")), co_color, Color.WHITE);
                    BufferedImage ta = aplicarFiltro(ImageIO.read(new File(getServletContext().getRealPath("/") + "/img/geo/ico_moto.png")), Color.RED, co_color);
                    BufferedImage cir = new BufferedImage(cr.getWidth(), cr.getHeight(), cr.getType());
                    AffineTransform tx = new AffineTransform();
                    tx.rotate(Math.toRadians(nu_angulo), cr.getWidth() / 2, cr.getHeight() / 2);
                    
                    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
                    cir = op.filter(cr, null).getSubimage(0, 0, 50, 50);
                    
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    ((Graphics2D) cir.getGraphics()).drawImage(ta, ((cr.getWidth() - ta.getWidth()) / 2), ((cr.getHeight() - ta.getHeight()) / 2), null);
                    ImageIO.write(cir, "png", out);
                    break;
                }
                case "5": {
                    /**
                     * MOTO LINEAL
                     */
//                    int nu_angulo = Integer.parseInt(request.getParameter("nu_angulo"));//angulo del vehiculo
//                    String no_colore = request.getParameter("no_color") == null ? "ffffff" : request.getParameter("no_color");//color
//                    Color co_color = new Color(Integer.valueOf(no_colore.substring(0, 2), 16), Integer.valueOf(no_colore.substring(2, 4), 16), Integer.valueOf(no_colore.substring(4, 6), 16));
//
//                    BufferedImage arrow = colorImage(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/arrow.png")), co_color, null);
//                    BufferedImage arrowR = new BufferedImage(arrow.getHeight(), arrow.getWidth(), arrow.getType());
//                    AffineTransform tx = new AffineTransform();
//                    tx.rotate(Math.toRadians(nu_angulo), arrow.getWidth() / 2, arrow.getHeight() / 2);
//
//                    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
//                    arrowR = op.filter(arrow, null).getSubimage(0, 0, 24, 24);
//
//                    ImageIO.write(arrowR, "png", out);
                    int nu_angulo = Integer.parseInt(request.getParameter("nu_angulo"));//angulo del vehiculo
                    String no_colore = request.getParameter("no_color") == null ? "ffffff" : request.getParameter("no_color");//color
                    Color co_color = new Color(Integer.valueOf(no_colore.substring(0, 2), 16), Integer.valueOf(no_colore.substring(2, 4), 16), Integer.valueOf(no_colore.substring(4, 6), 16));
                    BufferedImage cr = colorImage(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/ico_circu.png")), co_color, Color.WHITE);
                    BufferedImage ta = aplicarFiltro(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/ico_lineal.png")), Color.RED, co_color);
                    BufferedImage cir = new BufferedImage(cr.getWidth(), cr.getHeight(), cr.getType());
                    AffineTransform tx = new AffineTransform();
                    tx.rotate(Math.toRadians(nu_angulo), cr.getWidth() / 2, cr.getHeight() / 2);
                    
                    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
                    cir = op.filter(cr, null).getSubimage(0, 0, 50, 50);
                    
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    ((Graphics2D) cir.getGraphics()).drawImage(ta, ((cr.getWidth() - ta.getWidth()) / 2), ((cr.getHeight() - ta.getHeight()) / 2), null);
                    ImageIO.write(cir, "png", out);
                    break;
                }
                case "6": {
                    /**
                     * CASA
                     */
//                    int nu_angulo = Integer.parseInt(request.getParameter("nu_angulo"));//angulo del vehiculo
//                    String no_colore = request.getParameter("no_color") == null ? "ffffff" : request.getParameter("no_color");//color
//                    Color co_color = new Color(Integer.valueOf(no_colore.substring(0, 2), 16), Integer.valueOf(no_colore.substring(2, 4), 16), Integer.valueOf(no_colore.substring(4, 6), 16));
//
//                    BufferedImage arrow = colorImage(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/arrow.png")), co_color, null);
//                    BufferedImage arrowR = new BufferedImage(arrow.getHeight(), arrow.getWidth(), arrow.getType());
//                    AffineTransform tx = new AffineTransform();
//                    tx.rotate(Math.toRadians(nu_angulo), arrow.getWidth() / 2, arrow.getHeight() / 2);
//
//                    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
//                    arrowR = op.filter(arrow, null).getSubimage(0, 0, 24, 24);
//
//                    ImageIO.write(arrowR, "png", out);
                    int nu_angulo = Integer.parseInt(request.getParameter("nu_angulo"));//angulo del vehiculo
                    String no_colore = request.getParameter("no_color") == null ? "ffffff" : request.getParameter("no_color");//color
                    Color co_color = new Color(Integer.valueOf(no_colore.substring(0, 2), 16), Integer.valueOf(no_colore.substring(2, 4), 16), Integer.valueOf(no_colore.substring(4, 6), 16));
                    BufferedImage cr = colorImage(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/ico_circu.png")), co_color, Color.WHITE);
                    BufferedImage ta = aplicarFiltro(ImageIO.read(new File(getServletContext().getRealPath("/") + "img/geo/ico_casa.png")), Color.RED, co_color);
                    BufferedImage cir = new BufferedImage(cr.getWidth(), cr.getHeight(), cr.getType());
                    AffineTransform tx = new AffineTransform();
                    tx.rotate(Math.toRadians(nu_angulo), cr.getWidth() / 2, cr.getHeight() / 2);
                    
                    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
                    cir = op.filter(cr, null).getSubimage(0, 0, 50, 50);
                    
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                    ((Graphics2D) cir.getGraphics()).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    ((Graphics2D) cir.getGraphics()).drawImage(ta, ((cr.getWidth() - ta.getWidth()) / 2), ((cr.getHeight() - ta.getHeight()) / 2), null);
                    ImageIO.write(cir, "png", out);
                    break;
                }
            }
        } catch (NumberFormatException | IOException ex) {
            System.out.println("Error: " + ex);
        } finally {
            out.close();
        }
    }
    
    private static BufferedImage colorImage(BufferedImage image, Color color, Color color2) {
        int width = image.getWidth();
        int height = image.getHeight();
        WritableRaster raster = image.getRaster();
        
        if (color2 != null) {
            for (int xx = 0; xx < width; xx++) {
                for (int yy = 0; yy < height; yy++) {
                    int[] pixels = raster.getPixel(xx, yy, (int[]) null);
//                    System.out.print("(" + pixels[0] + "," + pixels[1] + "," + pixels[2] + ":"+pixels[3]+")" );
                    if (pixels[0] != 255 & pixels[1] != 255 & pixels[2] != 255) {
//                    if (pixels[0] != 0 & pixels[1] != 0 & pixels[2] != 0) {
                        pixels[0] = color.getRed();
                        pixels[1] = color.getGreen();
                        pixels[2] = color.getBlue();
                        raster.setPixel(xx, yy, pixels);
                    }
                }
                System.out.println("");
            }
        } else {
            for (int xx = 0; xx < width; xx++) {
                for (int yy = 0; yy < height; yy++) {
                    int[] pixels = raster.getPixel(xx, yy, (int[]) null);
                    pixels[0] = color.getRed();
                    pixels[1] = color.getGreen();
                    pixels[2] = color.getBlue();
                    raster.setPixel(xx, yy, pixels);
                }
            }
        }
        return image;
    }
    
    private static BufferedImage colorImage2(BufferedImage image, Color color, Color color2) {
        int width = image.getWidth();
        int height = image.getHeight();
        WritableRaster raster = image.getRaster();
        
        if (color2 != null) {
            for (int xx = 0; xx < width; xx++) {
                for (int yy = 0; yy < height; yy++) {
                    int[] pixels = raster.getPixel(xx, yy, (int[]) null);
//                    System.out.print("(" + pixels[0] + "," + pixels[1] + "," + pixels[2] + ":"+pixels[3]+")" );
//                    if (pixels[0] != 255 & pixels[1] != 255 & pixels[2] != 255) {
//                    if (pixels[0] != 0 & pixels[1] != 0 & pixels[2] != 0) {
                    if (pixels[0] != color2.getRed() & pixels[1] != color2.getGreen() & pixels[2] != color2.getBlue()) {
                        pixels[0] = color.getRed();
                        pixels[1] = color.getGreen();
                        pixels[2] = color.getBlue();
                        raster.setPixel(xx, yy, pixels);
                    }
                }
                System.out.println("");
            }
        } else {
            for (int xx = 0; xx < width; xx++) {
                for (int yy = 0; yy < height; yy++) {
                    int[] pixels = raster.getPixel(xx, yy, (int[]) null);
                    pixels[0] = color.getRed();
                    pixels[1] = color.getGreen();
                    pixels[2] = color.getBlue();
                    raster.setPixel(xx, yy, pixels);
                }
            }
        }
        return image;
    }
    
    public BufferedImage aplicarFiltro(BufferedImage image, Color deColor, Color aColor) {
        if (image != null) {
            WritableRaster raster = image.getRaster();
            int red = deColor.getRed();
            int green = deColor.getGreen();
            int blue = deColor.getBlue();
            int tolerancia = 200;
            for (int i = 0; i < image.getWidth(); i++) {
//                System.out.print("[" + i + "]  ");
                for (int j = 0; j < image.getHeight(); j++) {
                    int[] pixels = raster.getPixel(i, j, (int[]) null);
//                    System.out.print(" (" + pixels[0] + "," + pixels[1] + "," + pixels[2] + "," + pixels[3] + ")\t");
                    if (pixels[3] != 0) {
                        if (Math.pow(red - pixels[0], 2) + Math.pow(green - pixels[1], 2) + Math.pow(blue - pixels[2], 2) <= Math.pow(tolerancia, 2)) {
                            pixels[0] = aColor.getRed();
                            pixels[1] = aColor.getGreen();
                            pixels[2] = aColor.getBlue();
                            raster.setPixel(i, j, pixels);
                        }
                    }
                }
                System.out.println("");
            }
        }
//        return bi;
        return image;
    }
    
    public BufferedImage changeColor(BufferedImage image, Color mask, Color replacement) {
        BufferedImage destImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
        
        Graphics2D g = destImage.createGraphics();
        g.drawImage(image, null, 0, 0);
        g.dispose();
        
        for (int i = 0; i < destImage.getWidth(); i++) {
            for (int j = 0; j < destImage.getHeight(); j++) {
                int destRGB = destImage.getRGB(i, j);
                if (mask.getRGB() == destRGB) {
                    //ROJO
                    destImage.setRGB(i, j, replacement.getRGB());
                }
            }
        }
        
        return destImage;
    }
    
    private boolean matches(int maskRGB, int destRGB) {
        float[] hsbMask = getHSBArray(maskRGB);
        float[] hsbDest = getHSBArray(destRGB);
        
        if (hsbMask[HUE] == hsbDest[HUE]
                && hsbMask[SATURATION] == hsbDest[SATURATION]
                && getRGBArray(destRGB)[ALPHA] != TRANSPARENT) {
            
            return true;
        }
        return false;
    }
    
    private int getNewPixelRGB(int replacement, int destRGB) {
        float[] destHSB = getHSBArray(destRGB);
        float[] replHSB = getHSBArray(replacement);
        
        int rgbnew = Color.HSBtoRGB(replHSB[HUE],
                replHSB[SATURATION], destHSB[BRIGHTNESS]);
        return rgbnew;
    }
    
    private int[] getRGBArray(int rgb) {
        return new int[]{(rgb >> 24) & 0xff, (rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff};
    }
    
    private float[] getHSBArray(int rgb) {
        int[] rgbArr = getRGBArray(rgb);
        return Color.RGBtoHSB(rgbArr[RED], rgbArr[GREEN], rgbArr[BLUE], null);
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}

class BlueFilter extends RGBImageFilter {
    
    public BlueFilter() {
        canFilterIndexColorModel = true;
    }
    
    public int filterRGB(int x, int y, int rgb) {

//    return rgb & 0xFF0000FF; 
//        return ((rgb & 0xff00ff00)
        //R  G B
        return ((rgb & 0xff00ff00) | ((rgb & 0xff0000) >> 8) | ((rgb & 0xff) << 8));
    }
    
}
